﻿//******************************************************************************************************
//  EventDataLoader.cs - Gbtc
//
//  Copyright © 2013, Grid Protection Alliance.  All Rights Reserved.
//
//  Licensed to the Grid Protection Alliance (GPA) under one or more contributor license agreements. See
//  the NOTICE file distributed with this work for additional information regarding copyright ownership.
//  The GPA licenses this file to you under the Eclipse Public License -v 1.0 (the "License"); you may
//  not use this file except in compliance with the License. You may obtain a copy of the License at:
//
//      http://www.opensource.org/licenses/eclipse-1.0.php
//
//  Unless agreed to in writing, the subject software distributed under the License is distributed on an
//  "AS-IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. Refer to the
//  License for the specific language governing permissions and limitations.
//
//  Code Modification History:
//  ----------------------------------------------------------------------------------------------------
//  11/27/2013 - Stephen C. Wills
//       Generated original version of source code.
//
//******************************************************************************************************

using System;
using System.IO;
using System.Transactions;
using System.Windows.Forms;
using GSF.Data;
using GSF.ErrorManagement;
using GSF.IO;
using GSF.SELEventParser;

namespace IEDEDL
{
    public partial class EventDataLoader : Form
    {
        private LogFile m_errorLog;

        public EventDataLoader()
        {
            InitializeComponent();
        }

        private void LoadFile(string fileName)
        {
            EventFile eventFile;

            try
            {
                if (!File.Exists(fileName))
                    return;

                DisplayMessage(string.Format("Attempting to parse \"{0}\"...", Path.GetFileName(fileName)));
                eventFile = EventFile.Parse(fileName);

                DisplayMessage("Loading data into event database...");
                LoadData(eventFile);

                DisplayMessage(string.Format("Successfully loaded \"{0}\".", Path.GetFileName(fileName)));
            }
            catch (Exception ex)
            {
                m_errorLog.WriteTimestampedLine(ErrorLogger.GetExceptionInfo(ex, false));
                m_errorLog.Flush();

                DisplayMessage(string.Format("An exception occurred while loading {0}:", Path.GetFileName(fileName)));
                DisplayMessage(ex.Message);
                DisplayMessage("See ErrorLog.txt for more details.");
            }

            DisplayMessage(string.Empty);
        }

        private void LoadData(EventFile eventfile)
        {
            const string DeviceCountFormat = "SELECT COUNT(*) FROM Device WHERE DeviceCode = {0}";
            const string DeviceIDFormat = "SELECT ID FROM Device WHERE DeviceCode = {0}";
            const string InsertDeviceFormat = "INSERT INTO Device(DeviceCode, StationID) VALUES({0}, {1})";

            const string EventCountFormat = "SELECT COUNT(*) FROM Event WHERE DeviceID = {0} AND Time = {1}";
            const string EventInsertFormat = "INSERT INTO Event(DeviceID, Time, Type, CurrentMagnitude, FaultLocation, Frequency, EventGroup, Shot, Targets) VALUES({0}, {1}, {2}, {3}, {4}, {5}, {6}, {7}, {8})";

            const int Timeout = DataExtensions.DefaultTimeoutDuration;

            string parameterizedQuery;

            int deviceCount;
            int deviceID;

            int eventCount;

            int deviceInsertCount = 0;
            int eventInsertCount = 0;

            using (TransactionScope scope = new TransactionScope())
            {
                using (AdoDataConnection dataConnection = new AdoDataConnection("systemSettings"))
                {
                    foreach (EventHistory history in eventfile.EventHistories)
                    {
                        parameterizedQuery = dataConnection.ParameterizedQueryString(DeviceCountFormat, "deviceCode");
                        deviceCount = Convert.ToInt32(dataConnection.Connection.ExecuteScalar(parameterizedQuery, Timeout, history.Header.RelayID ?? string.Empty));

                        if (deviceCount == 0)
                        {
                            parameterizedQuery = dataConnection.ParameterizedQueryString(InsertDeviceFormat, "deviceCode", "stationID");
                            dataConnection.Connection.ExecuteNonQuery(parameterizedQuery, Timeout, history.Header.RelayID ?? string.Empty, history.Header.StationID ?? string.Empty);
                            deviceInsertCount++;
                        }

                        parameterizedQuery = dataConnection.ParameterizedQueryString(DeviceIDFormat, "deviceCode");
                        deviceID = Convert.ToInt32(dataConnection.Connection.ExecuteScalar(parameterizedQuery, Timeout, history.Header.RelayID));

                        foreach (EventHistoryRecord record in history.Histories)
                        {
                            parameterizedQuery = dataConnection.ParameterizedQueryString(EventCountFormat, "deviceID", "time");
                            eventCount = Convert.ToInt32(dataConnection.Connection.ExecuteScalar(parameterizedQuery, Timeout, deviceID, record.Time));

                            if (eventCount == 0)
                            {
                                parameterizedQuery = dataConnection.ParameterizedQueryString(EventInsertFormat, "deviceID", "time", "type", "currentMagnitude", "faultLocation", "frequency", "eventGroup", "shot", "targets");
                                dataConnection.Connection.ExecuteNonQuery(parameterizedQuery, Timeout, deviceID, record.Time, record.EventType, record.Current, record.FaultLocation, record.Frequency, record.Group, record.Shot, (object)record.Targets ?? DBNull.Value);
                                eventInsertCount++;
                            }
                        }
                    }
                }

                scope.Complete();
            }

            DisplayMessage(string.Format("Inserted {0} device records and {1} event records into database.", deviceInsertCount, eventInsertCount));
        }

        private void DisplayMessage(string message)
        {
            MessageListTextBox.AppendText(message);
            MessageListTextBox.AppendText(Environment.NewLine);
        }

        private void EventDataLoader_Load(object sender, EventArgs e)
        {
            m_errorLog = new LogFile();
            m_errorLog.FileName = "ErrorLog.txt";
            m_errorLog.Initialize();
            m_errorLog.Open();
        }

        private void EventDataLoader_Resize(object sender, EventArgs e)
        {
            LoadDataLinkLabel.Left = (Width - LoadDataLinkLabel.Width) / 2;
            MessageListTextBox.Width = Width - 40;
            MessageListTextBox.Height = Height - 122;
        }

        private void LoadDataLinkLabel_Click(object sender, EventArgs e)
        {
            using (OpenFileDialog dialog = new OpenFileDialog())
            {
                dialog.Filter = "SEL Event Files|*.eve;*.sel|Text Files|*.txt|All Files|*.*";
                
                if (dialog.ShowDialog(this) == DialogResult.OK)
                    LoadFile(dialog.FileName);
            }
        }

        private void EventDataLoader_FormClosed(object sender, FormClosedEventArgs e)
        {
            if ((object)m_errorLog != null)
            {
                m_errorLog.Close();
                m_errorLog.Dispose();
                m_errorLog = null;
            }
        }
    }
}
